package com.gavin.model;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.gavin.plugin.service.ITransService;
import com.gavin.utils.DateUtils;
import com.gavin.utils.XMLElement;

/**
 *  <pre>
 * ------------------------------
 *  数据模板
 *  支持转化成xml，json
 *  支持xml转化成Model对象
 *  仅支持String和基本数据类型，及其数组类型的数据
 * ------------------------------
 * @author wdm（l311576@sina.com）  @date 2018年3月20日
 * @version 1.0
 * </pre>
 */
public  class Model  implements Serializable, Cloneable {

	/**
	 * Comment for <code>serialVersionUID</code>
	 */
	private static final long serialVersionUID = 1L;

	private Map<String, JObject> kv;
	private Set<String> fields;// 属性名
	
	public Model() {
		kv = new HashMap<String, JObject>();
		fields = new HashSet<String>();
//		this.set("PRINT_GAVIN_TRANS_LOG", true);//默认打印事务日志
	}
	
	public Map<String, JObject> kv(){
		return kv;
	}

	// get start------------------------------------------------------------------------------------------------------
	public Object getObject(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		} else {
			return jObj.obj;
		}
	}
	
	/**
	 * 判断容器中指定对象是否存在
	 * @param field
	 * @return
	 */
	final public boolean exists(String field) {
		if(kv.get(field) != null){
			return true;
		}else{
			int start=field.indexOf("[");
			int end=field.indexOf("]");
			int dotStart=field.indexOf(".");
			if(start<end && start>0){
				String dmsField=field.substring(0,start);
				String subField=field.substring(end+2);
				String indexField=field.substring(start+1, end);
				int index=(Integer)kv.get(indexField).getValue();
				JObject jo=kv.get(dmsField);
				Model[] dms=(Model[]) jo.getValue();
				Model dm=dms[index];
				if(dm.getJObject(subField)!=null){
					return true;
				}
			}else if(dotStart>0){
				String dmsField=field.substring(0,dotStart);
				String subField=field.substring(dotStart+1);
				JObject jo=kv.get(dmsField);
				if(jo==null){
					return false;
				}
				Model dms=(Model) jo.getValue();
				if(dms.getJObject(subField)!=null){
					return true;
				}
			}
			return false;
		}
	}

	public static void main(String[] args) {
		Model[] aa=new Model[1];
		aa[0]=new Model();
		aa[0].set("ssd",222);

		Long[] l={1l,2l};
		Request request=Request.build().set("user",aa).set("i",0).set("sss",l);
		System.out.println(request.model().getJObject("user[i].ssd").getValue());
		System.out.println(request.model().getJObject("sss[i]").getValue());
	}

	public JObject getJObject(String field) {
		if(kv.get(field)!=null){
			return kv.get(field);
		}
		
		int start=field.indexOf("[");
		int end=field.indexOf("]");
		int dotStart=field.indexOf(".");
		if(start<end && start>0){
			String dmsField=field.substring(0,start);
			String indexField=field.substring(start+1, end);

//			update 2018-07-26
//			int index=(Integer)kv.get(indexField).getValue();
			if(dotStart>0){
				String subField=field.substring(end+2);
				JObject indexFieldValue=kv.get(indexField);
				int index=-1;
				if(indexFieldValue!=null){
					index=(Integer)kv.get(indexField).getValue();
				}else{
					index=Integer.valueOf(indexField);
				}

				JObject jo=kv.get(dmsField);
				Model[] dms=(Model[]) jo.getValue();
				if(index>=dms.length){
					throw new RuntimeException(dmsField+" value IndexOutOfBounds :"+(index+1)+" > "+dms.length);
				}
				Model dm=dms[index];
				return dm.getJObject(subField);
			}else{//数组 update 2019-02-14
				JObject jo=kv.get(dmsField);
				JObject indexFieldValue=kv.get(indexField);
				int index=-1;
				if(indexFieldValue!=null){
					index=(Integer)kv.get(indexField).getValue();
				}else{
					index=Integer.valueOf(indexField);
				}

				Object[] objects= (Object[]) jo.getValue();
				return new JObject(jo.getRealType(),objects[index]);
			}


		}else if(dotStart>0){
			String dmsField=field.substring(0,dotStart);
			String subField=field.substring(dotStart+1);
			JObject jo=kv.get(dmsField);
			if(jo==null){
				return null;
			}
			Model dms=(Model) jo.getValue();
			return dms.getJObject(subField);
		}
		
		return kv.get(field);
	}
	
	public void setJObject(String field, JObject value) {
		fields.add(field);
		kv.put(field, value);
	}	
	
	public Object get(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return jObj.obj;
	}		

	public Model getModel(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Model) jObj.obj;
	}

	public Model[] getModels(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Model[]) jObj.obj;
	}

	public String[] getStrings(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String[]) jObj.obj;
	}
	
	public Integer[] getIntegers(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Integer[])jObj.obj;
	}

	public Short[] getShorts(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Short[]) jObj.obj;
	}

	public Float[] getFloats(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Float[]) jObj.obj;
	}

	public String[] getDates(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String[]) jObj.obj;
	}

	public String[] getDateTimes(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String[]) jObj.obj;
	}

	public String[] getTimes(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String[]) jObj.obj;
	}

	public Double[] getDoubles(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Double[]) jObj.obj;
	}

	public Byte[] getBytes(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Byte[]) jObj.obj;
	}

	public Boolean[] getBooleans(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Boolean[]) jObj.obj;
	}

	public Long[] getLongs(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Long[]) jObj.obj;
	}
	
	public String getString(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String) jObj.obj;
	}
	
	public Integer getInteger(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return Integer.valueOf(String.valueOf(jObj.obj));
	}

	public Short getShort(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Short) jObj.obj;
	}

	public Float getFloat(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Float) jObj.obj;
	}

	public String getDate(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String) jObj.obj;
	}

	public String getDateTime(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String) jObj.obj;
	}

	public String getTime(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (String) jObj.obj;
	}

	public Double getDouble(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Double) jObj.obj;
	}

	public Byte getByte(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Byte) jObj.obj;
	}

	public Boolean getBoolean(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return (Boolean) jObj.obj;
	}

	public Long getLong(String field) {
		JObject jObj = kv.get(field);
		if (jObj == null) {
			return null;
		}
		return Long.valueOf(String.valueOf(jObj.obj));
	}	
	// get end------------------------------------------------------------------------------------------------------

	public Model currentTime(){
		this.set("currentTime", DateUtils.date2String(new Date()));
		return this;
	}

	public static String getFieldId(String strFieldText) {
		if (strFieldText.startsWith("{") == false) {
			return null;
		}
		if (strFieldText.endsWith("}") == false) {
			return null;
		}
		return strFieldText.substring(1, strFieldText.length() - 1);
	}

	@Deprecated
	public void setObject(String field, Object value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._obj, value));
	}
	
	public void set(String field, Byte value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._byte, value));
	}
	
	/**
	 * 反射设置值
	 * @param type
	 * @param field
	 * @param value
	 */
//	public void set(Class<?> type, String field, Object value) {
//		if(value==null)return;
//		fields.add(field);
//		kv.put(field, new JObject(DataType.getDataType(type.getSimpleName()), value));
//	}
	
	/**
	 * 根据数据类型添加数据
	 * 过滤空值
	 * @param dataType
	 * @param field
	 * @param value
	 */
	public void set(DataType dataType, String field, Object value){
		if(value==null){
			return;
		}
		switch (dataType) {
			case _Bytes:
				Byte[] bts=(Byte[])value;
				fields.add(field);
				kv.put(field, new JObject(DataType._bytes,DataType._byte, bts));
				break;
			case _Shorts:
				Short[] sts=(Short[])value;
				fields.add(field);
				kv.put(field, new JObject(DataType._shorts,DataType._short, sts));
				break;
			case _Integers:	
				Integer[] ints=(Integer[])value;
				fields.add(field);
				kv.put(field, new JObject(DataType._ints,DataType._int, ints));
				break;
			case _Longs:
				Long[] ls=(Long[])value;
				fields.add(field);
				kv.put(field, new JObject(DataType._longs,DataType._long, ls));
				break;
			case _Floats:
				Float[] fts=(Float[])value;
				fields.add(field);
				kv.put(field, new JObject(DataType._floats,DataType._float, fts));
				break;
			case _Doubles:
				Double[] ds=(Double[])value;
				fields.add(field);
				kv.put(field, new JObject(DataType._doubles, ds));
				break;
			case _Booleans:
				Boolean[] bs=(Boolean[])value;
				fields.add(field);
				kv.put(field, new JObject(DataType._booleans, bs));
				break;
			default:
				fields.add(field);
				kv.put(field, new JObject(dataType, value));
				break;	
		}
	}	

	public void set(String field, Short value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._short, value));
	}

	public void set(String field, Integer value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._int, value));
	}

	public void set(String field, String value) {
		fields.add(field);
		JObject jobj = new JObject(DataType._string, value);
		kv.put(field, jobj);
	}

	public void set(String field, Date value) {
		fields.add(field);
		JObject jobj = new JObject(DataType._string, DateUtils.date2String(value));
		kv.put(field, jobj);
	}

	public void set(String field, Long value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._long, value));
	}

	public void set(String field, Float value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._float, value));
	}

	public void set(String field, Double value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._double, value));
	}

	public void set(String field, Boolean value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._boolean, value));
	}

	public void set(String field, Model dataModel) {
		fields.add(field);
		kv.put(field, new JObject(DataType._m, dataModel));
	}

	public void set(String field, Object dataModel) {
		fields.add(field);
		kv.put(field, new JObject(DataType._obj, dataModel));
	}
	
	public void remove(String field) {
		fields.remove(field);
		kv.remove(field);
	}
	
	public void copy(Model dm){
		Map<String, JObject> kv=dm.kv();
		for (String field : kv.keySet()) {
			this.kv.put(field, kv.get(field));
			fields.add(field);
		}
	}
	//	set field end------------------------------------------------------------------------------------------------------------------------------------

	//	set array start------------------------------------------------------------------------------------------------------------------------------------
	public void set(String field, Integer[] value) {
		if(value==null){
			return;
		}
		fields.add(field);
		kv.put(field, new JObject(DataType._ints,DataType._int, value));
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}

	public void set(String field, Long[] value) {
		if(value==null){
			return;
		}
		fields.add(field);
		kv.put(field, new JObject(DataType._longs,DataType._long, value));
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}

	public void set(String field, Float[] value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._floats, DataType._float,value));
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}

	public void set(String field, Double[] value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._doubles,DataType._double, value));
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}

	public void set(String field, Boolean[] value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._booleans,DataType._boolean, value));
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}


	public void set(String field, String[] value) {
		fields.add(field);
		JObject jobj = new JObject(DataType._strings,DataType._string, value);
		kv.put(field, jobj);
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}

	public void set(String field, Byte[] value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._bytes,DataType._byte, value));
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}

	public void set(String field, Short[] value) {
		fields.add(field);
		kv.put(field, new JObject(DataType._shorts,DataType._short, value));
		kv.put(field+".length", new JObject(DataType._int,value.length));
	}


//	public void set(String field, byte[] value) {
//		fields.add(field);
//		kv.put(field, new JObject(DataType._bytes, DataType._byte,value));
//		kv.put(field+".length", new JObject(DataType._int,value.length));
//	}
//
//	public void set(String field, short[] value) {
//		fields.add(field);
//		kv.put(field, new JObject(DataType._shorts, DataType._short,value));
//		kv.put(field+".length", new JObject(DataType._int,value.length));
//	}
//
//	public void set(String field, int[] value) {
//		fields.add(field);
//		kv.put(field, new JObject(DataType._ints, DataType._int,value));
//		kv.put(field+".length", new JObject(DataType._int,value.length));
//	}
//
//	public void set(String field, long[] value) {
//		fields.add(field);
//		kv.put(field, new JObject(DataType._longs,DataType._long, value));
//		kv.put(field+".length", new JObject(DataType._int,value.length));
//	}
//
//	public void set(String field, float[] value) {
//		fields.add(field);
//		kv.put(field, new JObject(DataType._floats,DataType._float, value));
//		kv.put(field+".length", new JObject(DataType._int,value.length));
//	}
//
//	public void set(String field, double[] value) {
//		fields.add(field);
//		kv.put(field, new JObject(DataType._doubles,DataType._double, value));
//		kv.put(field+".length", new JObject(DataType._int,value.length));
//	}
//
//	public void set(String field, boolean[] value) {
//		fields.add(field);
//		kv.put(field, new JObject(DataType._booleans,DataType._boolean, value));
//		kv.put(field+".length", new JObject(DataType._int,value.length));
//	}

	public void set(String field, Model[] dataModels) {
		fields.add(field);
		kv.put(field, new JObject(DataType._ms,DataType._m, dataModels));
		kv.put(field+".length", new JObject(DataType._int,dataModels.length));
	}
	//	set array end------------------------------------------------------------------------------------------------------------------------------------

	/**
	 * 判断容器中是否有对象
	 * @return boolean
	 */
	final public boolean empty() {
		return kv.size() == 0;
	}

	final public Object[] fields() {
		return fields.toArray();
	}

	final public Set<String> fs() {
		return fields;
	}

	final public Object[] objects() {
		return kv.values().toArray();
	}

	final public int fieldCount() {
		return fields.size();
	}

	public Model clone() {
		return this.clone();
	}

	public String getServiceName(){
		return this.getString(ITransService.SERVICENAME_KEY);
	}
	
	public void setServiceName(String serviceName){
		this.set(ITransService.SERVICENAME_KEY, serviceName);
	}
	
	public String getTransName(){
		return this.getString(ITransService.TRANSNAME_KEY);
	}
	
	public void setTransName(String transName){
		this.set(ITransService.TRANSNAME_KEY,transName);
	}
	
	// 序列化方法 start-------------------------------------------------------------------------------------------------
	final public String toJson() {
		return toString();
	}

	public String toString() {
		StringBuilder sb = new StringBuilder("{");
		for (String field : fields) {
			JObject jobj = kv.get(field);
			sb.append("\"" + field + "\":");
			DataType dt = jobj.dataType;
			switch (dt) {
			case _int:
			case _long:
			case _double:
			case _float:
			case _short:	
			case _byte:					
			case _boolean:
				sb.append(String.valueOf(jobj.obj));
				break;
			case _string:
				sb.append("\"");
				sb.append(jobj.obj);
				sb.append("\"");
				break;
			case _m:
				Model dm = (Model) jobj.obj;
				sb.append(dm.toString());
				break;
			case _ints:
				int[] ints = (int[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < ints.length; i++) {
					sb.append(ints[i]);
					if(i+1<ints.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;
			case _longs:
				long[] longs = (long[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < longs.length; i++) {
					sb.append(longs[i]);
					if(i+1<longs.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;
			case _doubles:
				double[] doubles = (double[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < doubles.length; i++) {
					sb.append(doubles[i]);
					if(i+1<doubles.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;
			case _floats:
				float[] floats = (float[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < floats.length; i++) {
					sb.append(floats[i]);
					if(i+1<floats.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;
			case _bytes:
				byte[] bytes = (byte[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < bytes.length; i++) {
					sb.append(bytes[i]);
					if(i+1<bytes.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;				
			case _shorts:
				short[] shorts = (short[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < shorts.length; i++) {
					sb.append(shorts[i]);
					if(i+1<shorts.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;				
			case _booleans:	
				boolean[] booleans = (boolean[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < booleans.length; i++) {
					sb.append(booleans[i]);
					if(i+1<booleans.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;			
			case _date:
			case _datetime:
			case _time:				
			case _strings:	
				Object[] strs = (Object[]) jobj.obj;
				sb.append("[");
				for (int i = 0; i < strs.length; i++) {
					sb.append("\"").append(strs[i]).append("\"");
					if(i+1<strs.length){
						sb.append(",");
					}
				}
				sb.append("]");
				break;				
			case _ms:
				Model[] dms = (Model[]) jobj.obj;
				sb.append("[");
				boolean haschild = false;
				for (int i = 0; i < dms.length; i++) {
					sb.append(dms[i].toString()).append(",");
					haschild = true;
				}
				if (haschild) {
					sb.replace(sb.length() - 1, sb.length(), "");
				}
				sb.append("]");
				break;
			case _obj:
//				Object obj = (Object) jobj.obj;
//				String js = JSONObject.toJSONString(obj);
//				sb.append(js);
				sb.append( jobj.obj);
				break;
			default:
				sb.append("{}");
			}
			sb.append(",");
		}
		if(sb.length()>1)sb.replace(sb.length() - 1, sb.length(), "");
		sb.append("}");
		return sb.toString();
	}

	public final String toXML() {
		StringBuilder sb = xml();
		sb.insert(0, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		return sb.toString();
	}
	
	public final static Model fromXML(String modelXml) {
		XMLElement xmlNode=new XMLElement();
		xmlNode.parseString(modelXml);
		Model model=new Model();
		model.fromXML(xmlNode);
		return model;
	}

	private StringBuilder xml() {
		StringBuilder sb = new StringBuilder("<m>");
		for (String field : fields) {
			JObject jobj = kv.get(field);
			DataType dt = jobj.dataType;
			switch (dt) {
			case _int:
				sb.append("<n n=\"").append(field).append("\" v=\"");
				sb.append((int) jobj.obj);
				sb.append("\"/>");
				break;
			case _long:
				sb.append("<l n=\"").append(field).append("\" v=\"");
				sb.append((long) jobj.obj);
				sb.append("\"/>");
				break;
			case _double:
				sb.append("<db n=\"").append(field).append("\" v=\"");
				sb.append((double) jobj.obj);
				sb.append("\"/>");
				break;
			case _float:
				sb.append("<ft n=\"").append(field).append("\" v=\"");
				sb.append((float) jobj.obj);
				sb.append("\"/>");
				break;
			case _boolean:
				sb.append("<bn n=\"").append(field).append("\" v=\"");
				sb.append((boolean) jobj.obj);
				sb.append("\"/>");
				break;
			case _short:
				sb.append("<sh n=\"").append(field).append("\" v=\"");
				sb.append(this.getShort(field));
				sb.append("\"/>");
				break;
			case _byte:
				sb.append("<by n=\"").append(field).append("\" v=\"");
				sb.append(this.getByte(field));
				sb.append("\"/>");
				break;				
			case _string:
				sb.append("<s n=\"").append(field).append("\" v=\"");
				sb.append(jobj.obj);
				sb.append("\"/>");
				break;
			case _strings:
				sb.append("<ss n=\"").append(field).append("\" v=\"");
				String[] strs=this.getStrings(field);
				sb.append(strs[0]);
				for (int i = 1; i < strs.length; i++) {
					sb.append(",").append(strs[i]);
				}
				sb.append("\"/>");
				break;
			case _booleans:
				sb.append("<bns n=\"").append(field).append("\" v=\"");
				Boolean[] booleans=this.getBooleans(field);
				sb.append(booleans[0]);
				for (int i = 1; i < booleans.length; i++) {
					sb.append(",").append(booleans[i]);
				}
				sb.append("\"/>");
				break;				
			case _longs:
				sb.append("<ls n=\"").append(field).append("\" v=\"");
				Long[] longs=this.getLongs(field);
				sb.append(longs[0]);
				for (int i = 1; i < longs.length; i++) {
					sb.append(",").append(longs[i]);
				}
				sb.append("\"/>");
				break;
			case _ints:
				sb.append("<ns n=\"").append(field).append("\" v=\"");
				Integer[] ints=this.getIntegers(field);
				sb.append(ints[0]);
				for (int i = 1; i < ints.length; i++) {
					sb.append(",").append(ints[i]);
				}
				sb.append("\"/>");
				break;
			case _shorts:
				sb.append("<shs n=\"").append(field).append("\" v=\"");
				Short[] shorts=this.getShorts(field);
				sb.append(shorts[0]);
				for (int i = 1; i < shorts.length; i++) {
					sb.append(",").append(shorts[i]);
				}
				sb.append("\"/>");
				break;
			case _bytes:
				sb.append("<bys n=\"").append(field).append("\" v=\"");
				Byte[] bytes=this.getBytes(field);
				sb.append(bytes[0]);
				for (int i = 1; i < bytes.length; i++) {
					sb.append(",").append(bytes[i]);
				}
				sb.append("\"/>");
				break;
			case _doubles:
				sb.append("<dbs n=\"").append(field).append("\" v=\"");
				Double[] doubles=this.getDoubles(field);
				sb.append(doubles[0]);
				for (int i = 1; i < doubles.length; i++) {
					sb.append(",").append(doubles[i]);
				}
				sb.append("\"/>");
				break;
			case _floats:
				sb.append("<fts n=\"").append(field).append("\" v=\"");
				Float[] floats=this.getFloats(field);
				sb.append(floats[0]);
				for (int i = 1; i < floats.length; i++) {
					sb.append(",").append(floats[i]);
				}
				sb.append("\"/>");
				break;
			case _datetimes:
				sb.append("<dts n=\"").append(field).append("\" v=\"");
				String[] datetimes=this.getStrings(field);
				sb.append(datetimes[0]);
				for (int i = 1; i < datetimes.length; i++) {
					sb.append(",").append(datetimes[i]);
				}
				sb.append("\"/>");
				break;
			case _dates:
				sb.append("<des n=\"").append(field).append("\" v=\"");
				String[] dates=this.getStrings(field);
				sb.append(dates[0]);
				for (int i = 1; i < dates.length; i++) {
					sb.append(",").append(dates[i]);
				}
				sb.append("\"/>");
				break;	
			case _times:
				sb.append("<tes n=\"").append(field).append("\" v=\"");
				String[] times=this.getStrings(field);
				sb.append(times[0]);
				for (int i = 1; i < times.length; i++) {
					sb.append(",").append(times[i]);
				}
				sb.append("\"/>");
				break;	
			case _m:
				sb.append("<m n=\"").append(field).append("\">");
				Model dm = (Model) jobj.obj;
				sb.append(dm.xml());
				sb.append("</m>");
				break;
			case _ms:
				Model[] dms = (Model[]) jobj.obj;
				sb.append("<ms n=\"").append(field).append("\">");
				for (int i = 0; i < dms.length; i++) {
					sb.append(dms[i].xml());
				}
				sb.append("</ms>");
				break;
			case _obj:
				sb.append("<s n=\"").append(field).append("\" v=\"");
				sb.append(jobj.obj);
				sb.append("\"/>");
				break;
			default:
				sb.append("");
			}
		}
		sb.append("</m>");
		return sb;
	}
	// 序列化方法 end-------------------------------------------------------------------------------------------------

	// 反序列化方法 start-------------------------------------------------------------------------------------------------
	protected void fromXML(XMLElement xmlNode){//兼容CDO xml数据报文
		for(XMLElement node : xmlNode.getChildren()){
			String tag=node.getName();
			if(tag.equals("s") || tag.equals("dt") || tag.equals("de") || tag.equals("te")){//String  || tag.equals("STRF") || tag.equals("DF") || tag.equals("TF") || tag.equals("DTF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				this.set(name, value);
			} else if(tag.equals("bn") || tag.equals("BF")){//BooleanField
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				boolean bValue=false;
				if(value.equalsIgnoreCase("true")){
					bValue=true;
				}else if(value.equalsIgnoreCase("false")){
				}else{
					throw new RuntimeException("Parse xml error: unexpected boolean value "+value+" under "+tag);
				}
				this.set(name, bValue);
			} else if(tag.equals("by")){//ByteField  || tag.equals("BYF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				this.set(name, Byte.parseByte(value));
			} else if(tag.equals("sh")){//ShortField  || tag.equals("SF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				this.set(name, Short.parseShort(value));
			} 
//			else if(tag.equals("ch")){//ShortField
//				String name	=node.getStringAttribute("N");
//				String value=node.getStringAttribute("V");
//				this.set(name,(value));
//			}
			else if(tag.equals("n")){//IntegerField  || tag.equals("NF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				this.set(name, Integer.parseInt(value));
			} else if(tag.equals("l")){//LongField  || tag.equals("LF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				this.set(name, Long.parseLong(value));
			} else if(tag.equals("ft")){//FloatField  ||  tag.equals("FF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				this.set(name, Float.parseFloat(value));
			} else if(tag.equals("db")) {//Double  || tag.equals("DBLF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				this.set(name, Double.parseDouble(value));
			} else if(tag.equals("ss") || tag.equals("dts") || tag.equals("des") || tag.equals("tes")){//  || tag.equals("STRAF") || tag.equals("DAF") || tag.equals("TAF") || tag.equals("DTAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					this.set(name, arr);
				}
			} else if(tag.equals("fts")){// || tag.equals("FAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					float[] fts=new float[arr.length];
					for (int i = 0; i < arr.length; i++) {
						try{
							fts[i]=Float.parseFloat(arr[i]);
						}catch(Exception ex){
							throw new RuntimeException("Parse xml error: unexpected floats value "+arr[i]+" under "+tag);
						}
					}
					this.set(name, fts);
				}
			} else if(tag.equals("ns")){//  || tag.equals("NAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					int[] fts=new int[arr.length];
					for (int i = 0; i < arr.length; i++) {
						try{
							fts[i]=Integer.parseInt(arr[i]);
						}catch(Exception ex){
							throw new RuntimeException("Parse xml error: unexpected ints value "+arr[i]+" under "+tag);
						}
					}
					this.set(name, fts);
				}
			} else if(tag.equals("ls")) {// || tag.equals("LAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					long[] fts=new long[arr.length];
					for (int i = 0; i < arr.length; i++) {
						try{
							fts[i]=Long.parseLong(arr[i]);
						}catch(Exception ex){
							throw new RuntimeException("Parse xml error: unexpected longs value "+arr[i]+" under "+tag);
						}
					}
					this.set(name, fts);
				}
			} else if(tag.equals("dbs")) {// || tag.equals("DBLAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					double[] fts=new double[arr.length];
					for (int i = 0; i < arr.length; i++) {
						try{
							fts[i]=Double.parseDouble(arr[i]);
						}catch(Exception ex){
							throw new RuntimeException("Parse xml error: unexpected doubles value "+arr[i]+" under "+tag);
						}
					}
					this.set(name, fts);
				}
				
			} else if(tag.equals("shs")) {//  || tag.equals("SAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					short[] fts=new short[arr.length];
					for (int i = 0; i < arr.length; i++) {
						try{
							fts[i]=Short.parseShort(arr[i]);
						}catch(Exception ex){
							throw new RuntimeException("Parse xml error: unexpected shorts value "+arr[i]+" under "+tag);
						}
					}
					this.set(name, fts);
				}
			} else if(tag.equals("bys")) {//  || tag.equals("BYAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					byte[] fts=new byte[arr.length];
					for (int i = 0; i < arr.length; i++) {
						try{
							fts[i]=Byte.parseByte(arr[i]);
						}catch(Exception ex){
							throw new RuntimeException("Parse xml error: unexpected bytes value "+arr[i]+" under "+tag);
						}
					}
					this.set(name, fts);
				}
			} else if(tag.equals("bns")){//  || tag.equals("BAF")
				String name	=node.getStringAttribute("N");
				String value=node.getStringAttribute("V");
				if(value==null){
					
				}else{
					String[] arr=value.split(",");
					boolean[] bns=new boolean[arr.length];
					for (int i = 0; i < arr.length; i++) {
						boolean bValue=false;
						if("true".equalsIgnoreCase(arr[i])){
							bValue=true;
						}else if("false".equalsIgnoreCase(arr[i])){
						}else{
							throw new RuntimeException("Parse xml error: unexpected boolean value "+value+" under "+tag);
						}
						bns[i]=bValue;
					}
					this.set(name, bns);
				}				
			} else if(tag.equals("m")) {//  || tag.equals("CDO")
				String name	=node.getStringAttribute("N");
				Model modelValue	=new Model();
				modelValue.fromXML((XMLElement)node.getChildren().get(0));
				this.set(name, modelValue);
			} else if(tag.equals("ms")) {//  || tag.equals("CDOAF")
				String name	=node.getStringAttribute("N");
				ArrayList<XMLElement> alSubNode=node.getChildren();
				Model[] modelsValue=new Model[alSubNode.size()];
				for(int i=0;i<modelsValue.length;i++) {
					XMLElement subNode=alSubNode.get(i);
					String strSubNodeTag=subNode.getName();
					if(strSubNodeTag.equals("m")==false) {//   && strSubNodeTag.equals("CDO")==false
						throw new RuntimeException("Parse xml error: unexpected Tag name "+strSubNodeTag+" under "+tag);
					}
					Model modelValue=new Model();
					modelValue.fromXML(subNode);
					modelsValue[i]=modelValue;
				}
				this.set(name, modelsValue);
			} else{
				throw new RuntimeException("Parse xml error: unexpected Tag name ["+tag+"]");
			}
		}
	}
	
}
